package com.wg.net.server.http;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

import com.wg.net.annotation.InterceptorOrder;

/**
 * 全局拦截器管理器（支持动态注册、顺序控制、生命周期回调）
 *
 * @author 少爷123
 */
public class HandlerInterceptorMgr {
    private static final Log log = LogFactory.get(HandlerInterceptorMgr.class);
    /**
     * 线程安全的拦截器列表（支持动态增删）
     */
    private final List<HandlerInterceptor> interceptors = new CopyOnWriteArrayList<>();
    /**
     * 拦截器排序缓存（避免每次触发都排序）
     */
    private List<HandlerInterceptor> sortedInterceptors = Collections.emptyList();

    private HandlerInterceptorMgr() {
    }

    public static HandlerInterceptorMgr getInstance() {
        return Singleton.getManager();
    }

    /**
     * 初始化拦截器（扫描指定包并注册所有HandlerInterceptor实现类）
     *
     * @param basePackage 扫描的基础包路径（如"com.wg.interceptor"）
     */
    public void init(String basePackage) {
        scanAndRegisterInterceptors(basePackage);
        sortInterceptors(); // 初始化时排序
    }

    /**
     * 动态注册拦截器（运行时添加）
     *
     * @param interceptor 拦截器实例
     */
    public void registerInterceptor(HandlerInterceptor interceptor) {
        if (interceptor == null) {
            return;
        }
        interceptors.add(interceptor);
        sortInterceptors(); // 注册后重新排序
        log.debug("动态注册拦截器: {}", interceptor.getClass().getSimpleName());
    }

    /**
     * 动态注销拦截器（运行时移除）
     *
     * @param interceptor 拦截器实例
     */
    public void unregisterInterceptor(HandlerInterceptor interceptor) {
        if (interceptor == null) {
            return;
        }
        interceptors.remove(interceptor);
        sortInterceptors(); // 注销后重新排序
        log.debug("动态注销拦截器: {}", interceptor.getClass().getSimpleName());
    }

    /**
     * 触发所有拦截器的preHandle方法（按顺序执行）
     *
     * @param request  HTTP请求
     * @param response HTTP响应
     * @return true=中断后续逻辑；false=继续执行
     */
    public boolean triggerPreHandle(HttpServletRequest request, HttpServletResponse response) {
        if (CollUtil.isEmpty(sortedInterceptors)) {
            return false;
        }

        for (HandlerInterceptor interceptor : sortedInterceptors) {
            try {
                if (!interceptor.preHandle(request, response)) {
                    log.debug("拦截器中断请求 | 拦截器: {}", interceptor.getClass().getSimpleName());
                    return true;
                }
            } catch (Exception e) {
                log.error("拦截器preHandle执行异常 | 拦截器: {}", interceptor.getClass().getSimpleName(), e);
                // 异常时继续执行下一个拦截器（可根据需求调整为中断）
            }
        }
        return false;
    }

    /**
     * 触发所有拦截器的postHandle方法（按顺序执行）
     *
     * @param request  HTTP请求
     * @param response HTTP响应
     * @param handler  业务处理器
     */
    public void triggerPostHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (CollUtil.isEmpty(sortedInterceptors)) {
            return;
        }

        for (HandlerInterceptor interceptor : sortedInterceptors) {
            try {
                interceptor.postHandle(request, response, handler);
            } catch (Exception e) {
                log.error("拦截器postHandle执行异常 | 拦截器: {}", interceptor.getClass().getSimpleName(), e);
            }
        }
    }

    /**
     * 触发所有拦截器的afterCompletion方法（按顺序执行）
     *
     * @param request  HTTP请求
     * @param response HTTP响应
     * @param handler  业务处理器
     * @param ex       业务处理异常（无异常时为null）
     */
    public void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                       Exception ex) {
        if (CollUtil.isEmpty(sortedInterceptors)) {
            return;
        }

        for (HandlerInterceptor interceptor : sortedInterceptors) {
            try {
                interceptor.afterCompletion(request, response, handler, ex);
            } catch (Exception e) {
                log.error("拦截器afterCompletion执行异常 | 拦截器: {}", interceptor.getClass().getSimpleName(), e);
            }
        }
    }

    /**
     * 扫描指定包下的所有HandlerInterceptor实现类并注册
     *
     * @param basePackage 基础包路径
     */
    private void scanAndRegisterInterceptors(String basePackage) {
        Set<Class<?>> interceptorClasses = ClassUtil.scanPackageBySuper(basePackage, HandlerInterceptor.class);
        if (CollUtil.isEmpty(interceptorClasses)) {
            return;
        }

        List<Class<?>> validClasses = interceptorClasses.stream()
                .filter(clazz -> !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers()))
                .collect(Collectors.toList());

        for (Class<?> clazz : validClasses) {
            try {
                HandlerInterceptor interceptor = (HandlerInterceptor) ReflectUtil.newInstance(clazz);
                interceptors.add(interceptor);
                log.debug("扫描并注册拦截器: {}", clazz.getSimpleName());
            } catch (Exception e) {
                log.error("拦截器实例化失败 | 类: {}", clazz.getSimpleName(), e);
            }
        }
    }

    /**
     * 根据@InterceptorOrder注解对拦截器排序（升序）
     */
    private void sortInterceptors() {
        sortedInterceptors = interceptors.stream()
                .sorted(Comparator.comparingInt(interceptor -> {
                    InterceptorOrder order = interceptor.getClass().getAnnotation(InterceptorOrder.class);
                    return order != null ? order.value() : Integer.MAX_VALUE; // 未标注顺序的拦截器默认最后执行
                }))
                .collect(Collectors.toList());
        log.debug("拦截器排序完成，顺序: {}", sortedInterceptors.stream()
                .map(clazz -> clazz.getClass().getSimpleName())
                .collect(Collectors.toList()));
    }

    /**
     * 单例管理器（线程安全）
     */
    private static class Singleton {
        private static volatile HandlerInterceptorMgr INSTANCE;

        public static HandlerInterceptorMgr getManager() {
            if (INSTANCE == null) {
                synchronized (Singleton.class) {
                    if (INSTANCE == null) {
                        INSTANCE = new HandlerInterceptorMgr();
                    }
                }
            }
            return INSTANCE;
        }
    }
}